package com.jack.design_patterns.creational.prototype;

import org.openjdk.jol.vm.VM;

import java.util.HashMap;
import java.util.Map;

public class JackMybatis {

    // user缓存
    private Map<String, User> userCache = new HashMap<>();

    /**
     * 查询数据库获得user信息
     * @param username
     * @return
     */
    public User getUser(String username) {
        User user = getUserFromDB(username);
        return user;
    }

    /**
     * 模拟从数据库查询user数据
     * @return
     */
    private User getUserFromDB(String username) {
        System.out.println("从数据库查询到: " + username);
        User user = new User();
        user.setUsername(username);
        user.setAge(18);
        return user;
    }

    /**
     * 从缓存中获取user信息
     * @param username
     * @return
     */
    public User getUserFromCache(String username) {
        User user = null;
        if (!userCache.containsKey(username)) {
            user = getUserFromDBSaveToCache(username);
        } else {
            // 从缓存中直接拿数据，存在脏数据问题
            // 原型已经拿到，但是不能直接给出去(本人)
            user = userCache.get(username);
            // 解决方案：从原型对象中快速得到一个克隆体(克隆人)==>原型模式
        }
        return user;
    }

    /**
     * 从缓存中获取克隆的user信息
     * @param username
     * @return
     */
    public User getUserFromCacheWithClone(String username) throws Exception {
        User user = null;
        if (!userCache.containsKey(username)) {
            user = getUserFromDBSaveToCacheWithClone(username);
            System.out.println("从数据库获取到的user的地址值:" + VM.current().addressOf(user));
        } else {
            // 从缓存中直接拿数据，存在脏数据问题
            // 原型已经拿到，但是不能直接给出去(本人)
            user = userCache.get(username);
            System.out.println("从缓存中获取到的user的地址值:" + VM.current().addressOf(user));
            // 解决方案：从原型对象中快速得到一个克隆体(克隆人)==>原型模式
            user = (User) user.clone();
            System.out.println("从缓存中克隆user的地址值:" + VM.current().addressOf(user));
        }
        return user;
    }

    /**
     * 模拟从数据库查询user数据并放入缓存中
     * @param username
     * @return
     */
    private User getUserFromDBSaveToCache(String username) {
        System.out.println("从数据库查询到: " + username);
        User user = new User();
        user.setUsername(username);
        user.setAge(18);
        // 放入缓存中
        userCache.put(username, user);
        return user;
    }

    /**
     * 模拟从数据库查询user数据, 克隆一份原数据, 然后再放入缓存中
     * @param username
     * @return
     * @throws Exception
     */
    private User getUserFromDBSaveToCacheWithClone(String username) throws Exception {
        System.out.println("从数据库查询到: " + username);
        User user = new User();
        user.setUsername(username);
        user.setAge(18);
        System.out.println("放入缓存之前user的地址值:" + VM.current().addressOf(user));
        // 数据库查询到的数据,克隆一份放入缓存中
        userCache.put(username, (User) user.clone());
        System.out.println("从缓存中得到user的地址值:" + VM.current().addressOf(userCache.get(username)));
        return user;
    }
}
